Skip to content

Drop the float32 copies in the Wan block residual adds - #15225

Open
klin2024 wants to merge 1 commit into
huggingface:mainfrom
klin2024:dev/klin/wan-residual-no-float-copies
Open

klin2024 wants to merge 1 commit into
huggingface:mainfrom
klin2024:dev/klin/wan-residual-no-float-copies

Conversation

@klin2024

@klin2024 klin2024 commented Nov 9, 2026 •

Copy link
Copy Markdown

What does this PR do?

Fixes #15224

The Wan block computes its gated residual adds as (hidden_states.float() + attn_output * gate_msa) and (hidden_states.float() + ff_output.float() * c_gate_msa). gate_msa / c_gate_msa are already float32 (scale_shift_table + temb.float()), so type promotion does these adds in float32 anyway; the .float() calls only make full-size float32 copies in every block. This PR drops them. Output and gradients are bit-identical.

Same change in the Wan-derived blocks: Chronoedit and Wan-Animate (# Copied from, via make fix-copies), Helios, AnyFlow, AnyFlow-FAR, SkyReels-V2 and the Wan-VACE control block.

Transformer forward, eager, bf16, before -> after (ms):

model RTX 5090 speedup Radeon AI PRO R9700 speedup
Wan2.1-T2V-1.3B, 480x832, 81 frames 1591.7 -> 1570.4 1.014x 4258.1 -> 4202.8 1.013x
Wan2.2-TI2V-5B, 704x1280, 121 frames 3001.1 -> 2969.1 1.011x 7061.5 -> 6968.8 1.013x

RTX 5090: torch 2.14.1+cu130. R9700: torch 2.15.0a0+rocm10.1. diffusers main 8c54b38. Real transformer configs with random weights (timing does not depend on weight values), median of 6 forwards after warmup, 3 interleaved rounds per side; outputs bit-identical in every round on both GPUs. Gradients checked on the residual expression itself (with hidden_states also feeding a second branch, as in the block): bit-identical for bf16 / fp16 on CUDA, ROCm and CPU. (The model-level backward is not deterministic run to run on main already, so it cannot be compared bit for bit.)

Tests

Transformer tests of the touched models (Wan, Wan-VACE, Wan-Animate, Wan-Animate-2, Chronoedit, Helios, AnyFlow, AnyFlow-FAR, SkyReels-V2 and related, 12 files; GGUF / single-file / BFL tests deselected since they download full checkpoints), RTX 5090: 5 failed, 504 passed, 216 skipped. Main: the same counts and the same 5 test_compile_works_with_aot failures.

Self-review notes (self-review skill)

READY, no blocking issues. Left as is:

  • Wan-Animate-2 is not changed: its gate is self.modulation + temb without .float(), which is float32 only when modulation stays in float32 (_keep_in_fp32_modules via from_pretrained); after a plain .to(torch.bfloat16) dropping the cast would change the result.
  • No new test: the change is bit-identical by type promotion and covered by the existing model tests.

Before submitting

  • Did you use an AI agent (Claude Code, Codex, Cursor, etc.) to help with this PR? If so:
    • Did you read the Coding with AI agents guide?
    • Did you run the self-review skill on the diff?
    • Did you share the final self-review notes in the PR description or a comment?
  • Did you read the contributor guideline?
  • Did you read our philosophy doc? (important for complex PRs)
  • Was this discussed/approved via a GitHub issue or GitHub Discussions? Please add a link to it if that's the case.
  • Did you make sure to update the documentation with your changes? (no user-facing change)
  • Did you write any new necessary tests? (not needed, see above)
  • Are you the author (or part of the team we work with) of the model/pipeline this PR relates to?

cc @sayakpaul @dg845

@github-actions github-actions Bot added models fixes-issue size/S PR with diff < 50 LOC labels Nov 9, 2026
@klin2024
klin2024 marked this pull request as ready for review November 9, 2026 15:01
gate_msa / c_gate_msa are float32, so `hidden_states + attn_output * gate_msa`
is already computed in float32 through type promotion; the explicit .float()
calls only made full-size float32 copies of hidden_states and ff_output.
Same change in the Wan-derived blocks (Chronoedit and Wan-Animate via
make fix-copies, Helios, AnyFlow, AnyFlow-FAR, SkyReels-V2, Wan-VACE control
block). Bit-identical output and gradients.

Signed-off-by: Lin, KuanTing <Kuanting.Lin@amd.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fixes-issue models size/S PR with diff < 50 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wan transformer block makes float32 copies of hidden_states in its residual adds

1 participant